package de.g18.scavengerhunt.utils;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import de.g18.scavengerhunt.R;
import de.g18.scavengerhunt.activity.GameMapActivity;

public class NotificationUtil {

    // constants for notification handling
    private static final int           NOTIFICATION_ID_GAME_RUNNING          = 0;

    private static final int           NOTIFICATION_ID_GAME_OVER             = 1;

    private static final int           NOTIFICATION_ID_NO_GPS                = 2;

    private static final int           NOTIFICATION_ID_NO_NETWORK_CONNECTION = 3;

    private static final int           NOTIFICATION_ID_OUT_OF_BATTLEZONE     = 4;

    private static final int           MIN_MS_BETWEEN_NOTIFICATIONS          = 60000;

    private static Context             context                               = null;

    private static NotificationManager notificationManager                   = null;

    private static int                 notificationIcon                      = -1;

    private static boolean             isInitialized                         = false;

    private static long                lastOutOfBattleZoneNotification       = Long.MAX_VALUE - MIN_MS_BETWEEN_NOTIFICATIONS; // substract min value to prevent value to switch to min value

    /**
     * Initialize this util with an instance of the context, from where it's called
     * 
     * @param context
     */
    public static void initialize(Context context) {
        NotificationUtil.context = context;
        // get the notification manager
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        // get the notification handler from context
        notificationIcon = R.drawable.user_basecap;
        // display the ongoing notification while in a game session
        isInitialized = true;
        showGameRunningNotification();

    }

    /**
     * Remove the context from NotificationUtil, to avoid unwanted states, when the context has ended
     */
    public static void destroy() {
        context = null;
        isInitialized = false;
    }

    /**
     * Cancels all notifications (e.g. game has ended)
     */
    public static void dismissNotifications() {
        notificationManager.cancel(NOTIFICATION_ID_GAME_RUNNING);
        notificationManager.cancel(NOTIFICATION_ID_GAME_OVER);
        notificationManager.cancel(NOTIFICATION_ID_NO_GPS);
        notificationManager.cancel(NOTIFICATION_ID_NO_NETWORK_CONNECTION);
        notificationManager.cancel(NOTIFICATION_ID_OUT_OF_BATTLEZONE);
    }

    /**
     * Shows the ongoing notification, to indicate the game is running
     */
    public static void showGameRunningNotification() {
        if (isInitialized) {
            showNotification(context.getString(R.string.notificationGameRunning), NOTIFICATION_ID_GAME_RUNNING, true);
        }
    }

    /**
     * Show the 'out of battle zone' notification
     */
    public static void showOutOfBattleZoneNotification() {
        // show notification only after a configured amount of time
        if (isInitialized && (System.currentTimeMillis() - MIN_MS_BETWEEN_NOTIFICATIONS > lastOutOfBattleZoneNotification)) {
            showNotification(context.getString(R.string.notificationOutOfBattleZone), NOTIFICATION_ID_OUT_OF_BATTLEZONE, false);
            lastOutOfBattleZoneNotification = System.currentTimeMillis();
        }
    }

    /**
     * Show the 'game over' notification
     */
    public static void showGameOverNotification() {
        if (isInitialized) {
            showNotification(context.getString(R.string.evaderFound), NOTIFICATION_ID_GAME_OVER, false);
        }
    }

    /**
     * Show the 'no network connection' notification
     */
    public static void showNoNetworkConnectionNotification() {
        if (isInitialized) {
            showNotification(context.getString(R.string.notificationNoNetworkConnection), NOTIFICATION_ID_NO_NETWORK_CONNECTION, false);
        }
    }

    /**
     * Show the 'no GPS' notification
     */
    public static void showNoGpsNotification() {
        if (isInitialized) {
            showNotification(context.getString(R.string.notificationNoGps), NOTIFICATION_ID_NO_GPS, false);
        }
    }

    /**
     * Generic method to display a notification
     * 
     * @param notificationText The text shown in the notification and in the ticker
     * @param notificationId The id for the notification, see Constants in NotificationUtil
     * @param isOngoing set to true, if the notification shall be displayed all the time
     */
    private static void showNotification(CharSequence notificationText, int notificationId, boolean isOngoing) {
        // show the notification now...
        long now = System.currentTimeMillis();

        CharSequence notificationTitle = context.getString(R.string.app_name);

        Notification notification = new Notification(notificationIcon, notificationText, now);

        // ongoing notification only for the "game active" notification
        if (isOngoing) {
            notification.flags |= Notification.FLAG_ONGOING_EVENT;
        } else {
            notification.flags |= Notification.FLAG_AUTO_CANCEL; // dismiss on click
            notification.flags |= Notification.FLAG_SHOW_LIGHTS;
            notification.defaults |= Notification.DEFAULT_ALL; // use defaults for light, vibration & sound
        }

        // open the game map, when notification is clicked
        Intent notificationIntent = new Intent(context, GameMapActivity.class);
        PendingIntent notificationPendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

        notification.setLatestEventInfo(context, notificationTitle, notificationText, notificationPendingIntent);

        // display the notification
        notificationManager.notify(notificationId, notification);
    }
}